package com.smart.community.commons.monitor;

import com.smart.community.commons.log.StructuredLogger;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

/**
 * 智慧社区管理系统 - 日志告警服务
 * @author Wu.Liang
 * @date 2024-12-20
 * @description 提供日志告警功能，支持多种告警方式和告警策略
 * @version 1.0.0
 * @task 002_Step9_Subtask4_Logging_Configuration_Optimization
 */
@Slf4j
@Service
public class LogAlertService {
    private static final Logger logger = LoggerFactory.getLogger(LogAlertService.class);
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final Map<String, AlertConfig> ALERT_CONFIGS = new HashMap<>();
    private final Map<String, Long> lastAlertTimeMap = new ConcurrentHashMap<>();

    @Autowired
    private StructuredLogger structuredLogger;

    static {
        initAlertConfigs();
    }

    private static void initAlertConfigs() {
        ALERT_CONFIGS.put("CACHE_ERROR", new AlertConfig("CACHE_ERROR", 3 * 60 * 1000, "HIGH", true));
        ALERT_CONFIGS.put("DATABASE_CONNECTION", new AlertConfig("DATABASE_CONNECTION", 60 * 1000, "CRITICAL", true));
        ALERT_CONFIGS.put("ERROR_FREQUENCY", new AlertConfig("ERROR_FREQUENCY", 5 * 60 * 1000, "HIGH", true));
        ALERT_CONFIGS.put("LOG_FILE_SIZE", new AlertConfig("LOG_FILE_SIZE", 30 * 60 * 1000, "LOW", true));
        ALERT_CONFIGS.put("PERFORMANCE", new AlertConfig("PERFORMANCE", 10 * 60 * 1000, "MEDIUM", true));
        ALERT_CONFIGS.put("SLOW_QUERY", new AlertConfig("SLOW_QUERY", 2 * 60 * 1000, "MEDIUM", true));
        ALERT_CONFIGS.put("SYSTEM_ERROR", new AlertConfig("SYSTEM_ERROR", 0, "CRITICAL", true));
    }

    public void sendErrorFrequencyAlert(String errorType, long errorCount, long timeWindow) {
        String alertKey = "ERROR_FREQUENCY_" + errorType;
        if (!shouldSendAlert(alertKey, "ERROR_FREQUENCY")) return;
        Map<String, Object> alertData = new HashMap<>();
        alertData.put("alertType", "ERROR_FREQUENCY");
        alertData.put("alertLevel", "HIGH");
        alertData.put("errorType", errorType);
        alertData.put("errorCount", errorCount);
        alertData.put("timeWindow", timeWindow);
        alertData.put("alertTime", LocalDateTime.now().format(DATETIME_FORMATTER));
        String message = String.format("错误频率告警: %s 在 %d 分钟内出现 %d 次", errorType, timeWindow / 60000, errorCount);
        sendAlert(message, alertData);
    }

    public void sendSlowQueryAlert(String sql, long executionTime, long threshold) {
        String alertKey = "SLOW_QUERY";
        if (!shouldSendAlert(alertKey, "SLOW_QUERY")) return;
        Map<String, Object> alertData = new HashMap<>();
        alertData.put("alertType", "SLOW_QUERY");
        alertData.put("alertLevel", "MEDIUM");
        alertData.put("sql", sql.length() > 200 ? sql.substring(0, 200) + "..." : sql);
        alertData.put("executionTime", executionTime);
        alertData.put("threshold", threshold);
        alertData.put("alertTime", LocalDateTime.now().format(DATETIME_FORMATTER));
        String message = String.format("慢查询告警: SQL执行时间 %d ms，超过阈值 %d ms", executionTime, threshold);
        sendAlert(message, alertData);
    }

    public void sendSystemErrorAlert(String exceptionType, String exceptionMessage, Map<String, Object> context) {
        String alertKey = "SYSTEM_ERROR_" + exceptionType;
        if (!shouldSendAlert(alertKey, "SYSTEM_ERROR")) return;
        Map<String, Object> alertData = new HashMap<>();
        alertData.put("alertType", "SYSTEM_ERROR");
        alertData.put("alertLevel", "CRITICAL");
        alertData.put("exceptionType", exceptionType);
        alertData.put("exceptionMessage", exceptionMessage);
        alertData.put("context", context);
        alertData.put("alertTime", LocalDateTime.now().format(DATETIME_FORMATTER));
        String message = String.format("系统异常告警: %s - %s", exceptionType, exceptionMessage);
        sendAlert(message, alertData);
    }

    private boolean shouldSendAlert(String alertKey, String configKey) {
        AlertConfig config = ALERT_CONFIGS.get(configKey);
        if (config == null || !config.isEnabled()) return false;
        long currentTime = System.currentTimeMillis();
        Long lastTime = lastAlertTimeMap.get(alertKey);
        if (config.getInterval() == 0 || lastTime == null || (currentTime - lastTime) >= config.getInterval()) {
            lastAlertTimeMap.put(alertKey, currentTime);
            return true;
        }
        return false;
    }

    private void sendAlert(String message, Map<String, Object> alertData) {
        try {
            String level = (String) alertData.get("alertLevel");
            String emoji = getAlertEmoji(level);
            logger.warn("{} {} - {}", emoji, level, message);
            structuredLogger.logError("SYSTEM_ALERT", message, new RuntimeException(message));
        } catch (Exception e) {
            logger.error("发送告警失败: {}", message, e);
        }
    }

    private String getAlertEmoji(String level) {
        switch (level) {
            case "CRITICAL": return "🚨";
            case "HIGH": return "⚡";
            case "MEDIUM": return "⚠️";
            case "LOW": return "📢";
            default: return "ℹ️";
        }
    }

    public Map<String, Object> getAlertStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        Map<String, Object> lastAlertTimes = new HashMap<>();
        for (Map.Entry<String, Long> entry : lastAlertTimeMap.entrySet()) {
            lastAlertTimes.put(entry.getKey(), LocalDateTime.ofEpochSecond(entry.getValue() / 1000, 0, java.time.ZoneOffset.systemDefault().getRules().getOffset(java.time.Instant.now())).format(DATETIME_FORMATTER));
        }
        statistics.put("alertConfigs", ALERT_CONFIGS);
        statistics.put("lastAlertTimes", lastAlertTimes);
        statistics.put("totalAlertTypes", lastAlertTimeMap.size());
        return statistics;
    }

    private Map<String, Object> getServerInfo() {
        Map<String, Object> serverInfo = new HashMap<>();
        try {
            Runtime runtime = Runtime.getRuntime();
            serverInfo.put("hostName", java.net.InetAddress.getLocalHost().getHostName());
            serverInfo.put("hostAddress", java.net.InetAddress.getLocalHost().getHostAddress());
            serverInfo.put("osName", System.getProperty("os.name"));
            serverInfo.put("javaVersion", System.getProperty("java.version"));
            serverInfo.put("totalMemory", runtime.totalMemory());
            serverInfo.put("freeMemory", runtime.freeMemory());
            serverInfo.put("maxMemory", runtime.maxMemory());
        } catch (Exception e) {
            serverInfo.put("error", "获取服务器信息失败");
            logger.debug("获取服务器信息失败", e);
        }
        return serverInfo;
    }

    private static class AlertConfig {
        private final String alertType;
        private final long interval;
        private final String level;
        private final boolean enabled;
        public AlertConfig(String alertType, long interval, String level, boolean enabled) {
            this.alertType = alertType;
            this.interval = interval;
            this.level = level;
            this.enabled = enabled;
        }
        public String getAlertType() { return alertType; }
        public long getInterval() { return interval; }
        public String getLevel() { return level; }
        public boolean isEnabled() { return enabled; }
    }
}
